﻿using System;
using System.Data.Common;
using CoreEx.Database.Query.Translators;
namespace CoreEx.Database.Query.Expressions
{
    /// <summary>
    /// Provides the base class from which the classes that represent expression tree nodes are derived.
    /// </summary>
    public abstract class DbExpression
    {
        

        [ThreadStatic]
        private static DbQueryTranslator _dbQueryTranslator;
        
        protected static readonly DbExpressionFactory ExpressionFactory = new DbExpressionFactory();


        

        /// <summary>
        /// Gets the <see cref="DbExpressionType"/> of the <see cref="DbExpression"/>.
        /// </summary>
        public abstract DbExpressionType ExpressionType { get; }


        #region Operator Overloads

        /// <summary>
        /// Implements the operator ==.
        /// </summary>
        /// <param name="leftExpression">The left expression.</param>
        /// <param name="rightExpression">The right expression.</param>
        /// <returns>The result of the operator.</returns>
        public static DbExpression operator == (DbExpression leftExpression, DbExpression rightExpression)
        {
            return ExpressionFactory.Equal(leftExpression, rightExpression);
        }


        /// <summary>
        /// Implements the operator ==.
        /// </summary>
        /// <param name="leftExpression">The left expression.</param>
        /// <param name="rightExpression">The right expression.</param>
        /// <returns>The result of the operator.</returns>
        public static DbExpression operator ==(DbExpression leftExpression, object value)
        {
            return ExpressionFactory.Equal(leftExpression, ExpressionFactory.Constant(value));
        }

        /// <summary>
        /// Implements the operator ==.
        /// </summary>
        /// <param name="leftExpression">The left expression.</param>
        /// <param name="rightExpression">The right expression.</param>
        /// <returns>The result of the operator.</returns>
        public static DbExpression operator ==(object value, DbExpression leftExpression)
        {
            return ExpressionFactory.Equal(leftExpression, ExpressionFactory.Constant(value));
        }
        
        /// <summary>
        /// Implements the operator ==.
        /// </summary>
        /// <param name="leftExpression">The left expression.</param>
        /// <param name="rightExpression">The right expression.</param>
        /// <returns>The result of the operator.</returns>
        public static DbExpression operator !=(object value, DbExpression rightExpression)
        {
            return ExpressionFactory.Equal(ExpressionFactory.Constant(value),rightExpression );
        }

        /// <summary>
        /// Implements the operator ==.
        /// </summary>
        /// <param name="leftExpression">The left expression.</param>
        /// <param name="rightExpression">The right expression.</param>
        /// <returns>The result of the operator.</returns>
        public static DbExpression operator !=(DbExpression leftExpression, object value)
        {
            return ExpressionFactory.Equal(leftExpression, ExpressionFactory.Constant(value));
        }



        /// <summary>
        /// Implements the operator &amp;.
        /// </summary>
        /// <param name="leftExpression">The left expression.</param>
        /// <param name="rightExpression">The right expression.</param>
        /// <returns>The result of the operator.</returns>
        public static DbExpression operator &(DbExpression leftExpression, DbExpression rightExpression)
        {
            return ExpressionFactory.And(leftExpression, rightExpression);
        }

        /// <summary>
        /// Implements the operator !=.
        /// </summary>
        /// <param name="leftExpression">The left expression.</param>
        /// <param name="rightExpression">The right expression.</param>
        /// <returns>The result of the operator.</returns>
        public static DbExpression operator !=(DbExpression leftExpression, DbExpression rightExpression)
        {
            return ExpressionFactory.NotEqual(leftExpression, rightExpression);
        }



        #endregion

        /// <summary>
        /// Returns a <see cref="System.String"/> that represents this instance.
        /// </summary>
        /// <returns>
        /// A <see cref="System.String"/> that represents this instance.
        /// </returns>
        public override string ToString()
        {
            InitializeQueryTranslator();
            return _dbQueryTranslator.Translate(this).Sql;
        }

        private static void InitializeQueryTranslator()
        {
            if (_dbQueryTranslator == null)            
                _dbQueryTranslator = DbProviderFactories.GetFactory("System.Data.SqlClient").CreateQueryTranslator();                            
        }
    }
}
